<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue'
import { BasicTableColumn } from '@/types'
import {
  FileInfo,
  FileInfoAddType,
  FileInfoEditType,
  ConditionSelectorParams,
  FileUpload
} from '@/types/modules/file-info'
import { formatToDateTime } from '@/utils/dateUtil'
import { useModal } from '@/hooks/system/useModal'
import { BasicModal as BModal } from '@/components/Modal'
import { useDrawer } from '@/hooks/system/useDrawer'
import AddedByDetail from '@/views/user/detail.vue'
import { useI18n } from '@/hooks/web/useI18n'
import { useHttp } from '@/hooks/web/useHttp'
import { useTableList } from '@/hooks/system/useTableList'
import * as api from '@/api/modules/file-info'
import search from './components/search.vue'
import list from './components/list.vue'
import add from './add.vue'
import edit from './edit.vue'
import detail from './detail.vue'
import { AxiosResponse } from 'axios'

import { message } from 'ant-design-vue'

const { t } = useI18n()

const searchParams: ConditionSelectorParams = reactive({})

let basicData: BasicTableColumn<FileInfo>[] = [
  {
    title: '文件ID',
    dataIndex: 'fileId',
    ellipsis: true
  },
  {
    title: '访问链接',
    dataIndex: 'url',
    type: 'link',
    ellipsis: true
  },
  {
    title: '组名',
    dataIndex: 'groupName'
  },
  {
    title: '文件名',
    dataIndex: 'name',
    ellipsis: true
  },
  {
    title: '文件扩展',
    dataIndex: 'extension'
  },
  {
    title: '文件大小',
    dataIndex: 'size'
  },
  {
    title: '由谁上传',
    dataIndex: 'addedBy',
    isCheck: true,
    name: 'name',
    ellipsis: true
  },
  {
    title: '哈希值',
    dataIndex: 'hash',
    ellipsis: true
  },
]

const { columns, pageParams, tableData, total, getData } =
  useTableList<FileInfo>(basicData)

onMounted(() => {
  getDataList()
})

const getDataList = getData<ConditionSelectorParams>(api.getConditionSelector, searchParams)

const onSearch = () => {
  pageParams.value.pageNum = 1
  getDataList()
}

const deleteDataHttp = useHttp(
  t('system.api.deleteError'),
  t('system.api.deleteSuccess')
)
const hanldeDeleteData = async (fileInfo: FileInfo) => {
  const res = await api.deleteFileInfo(fileInfo.id)
  deleteDataHttp(res, getDataList)
}

const addFormRef = ref()
const {
  bindValue: addBindValue,
  register: addRegister,
  onShow: onShowAdd,
  onClose: onCloseAdd,
  getInnerForm: getAddForm
} = useModal<FileUpload>()
const handleAddResult = useHttp(
  t('system.api.addError'),
  t('system.api.addSuccess')
)

const onFinishAdd = async function () {
  const result = await getAddForm<FileInfoAddType>(addFormRef)

  if (result) {
    getDataList()
    onCloseAdd()
  }
}

const editFormRef = ref()
const {
  bindValue: editBindValue,
  register: editRegister,
  currentItem: editCurrentItem,
  onShow: onShowEdit,
  onClose: onCloseEdit,
  getInnerForm: getEditForm
} = useModal<FileInfo>()
const handleEditResult = useHttp(
  t('system.api.editError'),
  t('system.api.editSuccess')
)

const onFinishEdit = async function () {
  const result = await getEditForm<FileInfoEditType>(editFormRef)
  if (result) {
    const res = await api.updateFileInfo(result, editCurrentItem.value?.id)
    handleEditResult(res, () => {
      getDataList()
      onCloseEdit()
    })
  }
}

const {
  visible: detailVisible,
  currentItem: detailCurrentItem,
  onShow: onShowDetail
} = useDrawer<FileInfo>()

const {
  visible: relateVisible,
  currentItem: relateCurrentItem,
  onShow: onShowRelate
} = useDrawer()

const relateComps = {
  addedBy: AddedByDetail,
}

const relateAttrName = ref<string>('')
const relateTitle = ref<string>('')
const onCheckRelate = (attrName: string, title: string, relate: any) => {
  relateAttrName.value = attrName
  relateTitle.value = title
  onShowRelate(relate)
}

const key = 'callback';
const downloading = ref(true);

const onDownload = async (row: FileInfo) => {
  let res = api.download(row, donwloadCallback)
    .then(res => {
    if (res.status == 200) {
      localDownload(row, res)
    }
  })
}

const localDownload = (row: FileInfo, res: AxiosResponse) => {
  let blob = new Blob([res.data], { type: 'application/octet-stream' });  
  let url = window.URL.createObjectURL(blob);

  let a = document.createElement('a');
  a.href = url;
  a.download = row.name as string;
  a.click();

  window.URL.revokeObjectURL(url);
  downloading.value = false;
}

const donwloadCallback = (percent: number) => {
  if (percent >= 100) {
    message.destroy()
    message.success('下载完成', 2.5)

    return;
  }
  if (!downloading.value) {
    message.loading({ content: `下载进度：${percent}%`, key, duration: 0 })
      
    downloading.value = true;
  } else {
    message.loading({ content: `下载进度：${percent}%`, key, duration: 0 })
  }
}
</script>

<template>
  <div class="page-wrapper">
    <a-card class="search-card">
      <search :formState="searchParams" @search="onSearch" />
    </a-card>
    <a-card class="table-card">
      <list v-bind="{ pageParams, total, columns, tableData }" title="文件信息" @add="onShowAdd" @refresh="getDataList"
        @check="onCheckRelate">
        <template #operate="row">          
          <a type="link" @click="onDownload(row)">下载</a>
          <a-divider type="vertical" />
          <a type="link" @click="onShowDetail(row)">{{ t('system.detail') }}</a>
          <a-divider type="vertical" />
          <a type="link" @click="onShowEdit(row)">{{ t('system.edit') }}</a>
          <a-divider type="vertical" />
          <a-popconfirm :title="t('system.deletePrompt')" placement="left" @confirm="hanldeDeleteData(row)">
            <a type="link" class="ap-action-danger-btn">{{
              t('system.delete')
              }}</a>
          </a-popconfirm>
        </template>
      </list>
    </a-card>

    <b-modal v-bind="addBindValue" :title="'上传'" @register="addRegister" @ok="onFinishAdd">
      <add ref="addFormRef" :item-data="{ files: []}"/>
    </b-modal>

    <b-modal v-bind="editBindValue" :title="t('system.modal.edit')" @register="editRegister" @ok="onFinishEdit">
      <edit ref="editFormRef" :item-data="editCurrentItem" />
    </b-modal>

    <a-drawer v-model:visible="detailVisible" :title="t('system.modal.detail')" :push="false" width="40vw"
      placement="right">
      <detail :item-data="detailCurrentItem" />
    </a-drawer>

    <a-drawer v-model:visible="relateVisible" :title="relateTitle" width="40vw" placement="right">
      <component :is="relateComps[relateAttrName]" :item-data="relateCurrentItem" />
    </a-drawer>
  </div>
</template>

<style lang="less" scoped>
.page-wrapper {
  padding: 20px;

  .table-card {
    margin-top: 20px;
  }
}

.drawer-footer {
  text-align: right;

  button {
    margin-left: 8px;
  }
}
</style>
